<?php
/**
 * Created by IntelliJ IDEA.
 * User: zhangjing60
 * Date: 17/8/14
 * Time: 下午4:15
 */

namespace BaiduBce\Services\Route;

use BaiduBce\Auth\BceV1Signer;
use BaiduBce\BceBaseClient;
use BaiduBce\Http\BceHttpClient;
use BaiduBce\Http\HttpHeaders;
use BaiduBce\Http\HttpMethod;
use BaiduBce\Http\HttpContentTypes;

class RouteClient extends BceBaseClient {
    
    private $signer;
    private $httpClient;
    private $prefix = '/v1';

    /**
     * RouteClient constructor.
     * @param array $config
     */
    function __construct(array $config)
    {
        parent::__construct($config, 'route');
        $this->signer = new BceV1Signer();
        $this->httpClient = new BceHttpClient();
    }

    /**
     * @param string $routeTableId  
     *        The id of the route table
     * 
     * @param string $clientToken 
     *         if the clientToken is not specified by the user, a random String
     *         generated by default algorithm will be used.
     * 
     * @param string $sourceAddress
     *        the source address of the route 
     * 
     * @param string $destinationAddress
     *         the destination address of the route
     * 
     * @param string $nexthopId
     *        the next hop id
     *        when the nexthopType is "defaultGateway",this field can be empty
     * 
     * @param string $nexthopType
     *        route type
     *        the Bcc type is "custom";
     *        the VPN type is "VPN";
     *        the NAT type is "NAT";
     *        the local gateway type is "defaultGateway"
     * 
     * @param string $description
     *        the option param to describe the route table
     * 
     * @param array $options
     *        The optional bce configuration, which will overwrite the
     *         default configuration that was passed while creating EipClient instance.
     * 
     * @return mixed
     * 
     */
    public function createRouteRule($routeTableId,  $sourceAddress, $destinationAddress,
    $nexthopType, $description, $nexthopId = null, $clientToken = null, $options = array()) {
        list($config) = $this->parseOptions($options, 'config');
        $params = array();
        $body = array();
        if (empty($clientToken)) {
            $params['clientToken'] = $this->generateClientToken();
        }
        else {
            $params['clientToken'] = $clientToken;
        }
        if (empty($routeTableId)) {
            throw new \InvalidArgumentException(
                'request $routeTableId  should not be empty .'
            );
        }
        if (empty($sourceAddress)) {
            throw new \InvalidArgumentException(
                'request $sourceAddress  should not be empty .'
            );
        }
        if (empty($destinationAddress)) {
            throw new \InvalidArgumentException(
                'request $destinationAddress  should not be empty .'
            );
        }
        if (empty($nexthopType)) {
            throw new \InvalidArgumentException(
                'request $nexthopType  should not be empty .'
            );
        }
        if (empty($description)) {
            throw new \InvalidArgumentException(
                'request $descrption  should not be empty .'
            );
        }
        $body['routeTableId'] = $routeTableId;
        $body['sourceAddress'] = $sourceAddress;
        $body['destinationAddress'] = $destinationAddress;
        $body['nexthopId'] = $nexthopId;
        $body['nexthopType'] = $nexthopType;
        $body['description'] = $description;
        return $this->sendRequest(
            HttpMethod::POST,
            array(
                'config' => $config,
                'params' => $params,
                'body' => json_encode($body),
            ),
            '/route/rule'
        );
        
    }

    /**
     * @param string $routeTableId
     *        the id of the route table
     *        vpcId and routeTableId cannot be empty at the same time
     * 
     * @param string $vpcId
     *        the vpc id 
     *        vpcId and routeTableId cannot be empty at the same time 
     * 
     * @param array $options
     *        The optional bce configuration, which will overwrite the
     *         default configuration that was passed while creating EipClient instance.
     * 
     * @return mixed
     * 
     */
    public function getRouteTable( $vpcId = null, $routeTableId = null, $options = array()) {
        list($config) = $this->parseOptions($options, 'config');
        $params = array();
        if (empty($routeTableId)  && empty($vpcId )) {
            throw new \InvalidArgumentException(
                'request $routeTableId and $vpcId should not be empty at the same time.'
            );
        }
        if (!empty($routeTableId)) {
            $params['routeTableId'] = $routeTableId;
        }
        if (!empty($vpcId)) {
            $params['vpcId'] = $vpcId;
        }

        return $this->sendRequest(
            HttpMethod::GET,
            array(
                'config' => $config,
                'params' => $params,
            ),
            '/route'
        );

    }

    /**
     * @param string $routeTableId
     *        the id of the specified route table
     * @param string $clientToken
     *        if the clientToken is not specified by the user, a random String
     *         generated by default algorithm will be used.
     * 
     * @param array $options
     *        The optional bce configuration, which will overwrite the
     *         default configuration that was passed while creating EipClient instance.
     * 
     * @return mixed
     * 
     */
    public function deleteRouteRule($routeRuleId, $clientToken = null, $options = array()) {
        $params = array();
        list($config) = $this->parseOptions($options, 'config');
        if(empty($routeRuleId) ) {
            throw new \InvalidArgumentException(
                'request $routeRuleId should not be empty.'
            );
        }
        // $params['routeRuleId'] = $routeRuleId;
        
        if (empty($clientToken)) {
            $params['clientToken'] = $this->generateClientToken();
        } else {
            $params['clientToken'] = $clientToken;
        }

        return $this->sendRequest(
            HttpMethod::DELETE,
            array(
                'config' => $config,
                'params' => $params,
            ),
            '/route/rule/' .$routeRuleId
        );
    }

    /**
     * Create HttpClient and send request
     *
     * @param string $httpMethod
     *          The Http request method
     *
     * @param array $varArgs
     *          The extra arguments
     *
     * @param string $requestPath
     *          The Http request uri
     *
     * @return mixed The Http response and headers.
     */
    private function sendRequest($httpMethod, array $varArgs, $requestPath = '/')
    {
        $defaultArgs = array(
            'config' => array(),
            'body' => null,
            'headers' => array(),
            'params' => array(),
        );

        $args = array_merge($defaultArgs, $varArgs);
        if (empty($args['config'])) {
            $config = $this->config;
        } else {
            $config = array_merge(
                array(),
                $this->config,
                $args['config']
            );
        }
        if (!isset($args['headers'][HttpHeaders::CONTENT_TYPE])) {
            $args['headers'][HttpHeaders::CONTENT_TYPE] = HttpContentTypes::JSON;
        }
        $path = $this->prefix . $requestPath;
        $response = $this->httpClient->sendRequest(
            $config,
            $httpMethod,
            $path,
            $args['body'],
            $args['headers'],
            $args['params'],
            $this->signer
        );

        $result = $this->parseJsonResult($response['body']);

        return $result;
    }
    /**
     * The default method to generate the random String for clientToken if the optional parameter clientToken
     * is not specified by the user.
     *
     * The default algorithm is Mersenne Twister to generate a random UUID,
     * @return String An random String generated by Mersenne Twister.
     */
    public static function generateClientToken()
    {
        $uuid = md5(uniqid(mt_rand(), true));
        return $uuid;
    }
}